package poker;
import java.util.*;

class Bot extends Player {
    private static final int NUM_OF_RANKS = 13;
	private static final int HIGH_CARD_RANK = 1;
    private static final int PAIR_RANK = 2;
    private static final int TWO_PAIR_RANK = 3;
    private static final int THREE_RANK = 4;
    private static final int STRAIGHT_RANK = 5;
    private static final int FLUSH_RANK = 6;
    private static final int STRAIGHT_FLUSH_RANK = 9;
    private static final int JACK_RANK = 9;
    private static final int HAND_SIZE = 5;
	private int bet;
	private int raise;
	private boolean bluffed;
	
	Bot(String name) 
	{
			super(name);
	}

	@Override
	public int[] picks() 
	{
		int myrank = evaluateHand();
		int[] myranks = getHand().getRanks();
		int[] result;
		int amount = 0;
		if (myrank <= STRAIGHT_FLUSH_RANK && myrank >= STRAIGHT_RANK)
		{
			amount = 0;
			result = new int[amount];
		}
		else if (myrank == THREE_RANK || myrank == PAIR_RANK)
		{
			for (int i = 0; i < NUM_OF_RANKS; i++)
			{
				if (myranks[i] == 1 && i < JACK_RANK)
				{
					amount++;
				}
			}
			result = new int[amount];
			for (int i = 0; i < NUM_OF_RANKS; i++)
			{
			if (myranks[i] == 1 && i < JACK_RANK)
			{
				result[amount - 1] = getHand().findRankIndex(i);
				amount--;
			}
			if (amount == 0)
			{
				break;
			}
		}
			for (int i = 0; i < amount; i++)
			{
				for (int j = 0; j < NUM_OF_RANKS; j++)
				{
					if (myranks[j] == 1 && j < JACK_RANK)
					{
						result[i] = getHand().findRankIndex(j);
					}
				}
			}            
		}
		else if (myrank == TWO_PAIR_RANK)
		{
			amount = 1;
			result = new int[amount];
			for (int i = 0; i < NUM_OF_RANKS; i++)
			{
				if (myranks[i] == 1)
				{
					result[amount - 1] = getHand().findRankIndex(i);
				}
			}
		}
		else
		{
			amount = 4;
			result = new int[amount];
			for (int i = 0; i < NUM_OF_RANKS; i++)
			{
				if (myranks[i] == 1)
				{
					result[HAND_SIZE - 1 - amount] = getHand().findRankIndex(i);
					amount--;
					if (amount == 0)
					{
						break;
					}
				}
			}
		}
		/*
			Random rand = new Random();
			int i = 0, curr;
			int amount = rand.nextInt(HAND_SIZE);
			int[] pick = new int[amount];
			while (i < amount) {
					curr = rand.nextInt(HAND_SIZE);
					if (!find(curr, pick, i)) {
							pick[i] = curr;
							i++;
					}
			}*/
		return result;
	}
	
	public String buyIn()
	{
		return "buyin";
	}
	
	public String action(int currBid, boolean allIn)
	{
		//String action = new String();
		/*
		int diff = currBid - getBid();
		if(currBid == 0 && getChips() > 10)
		{
			return "bet";
		}
		else if(diff <= 10 && getChips() > 10)
		{
			return "raise";
		}
		else if(diff <= 20 && getChips() > 20)
		{
			return "call";
		}
		else if(diff == 0)
		{
			return "check";
		}
		else if(diff>getChips())
		{
			return "quit";
		}
		else
		{
			return "fold";
		}
		*/
		
		//strategia licytowania
		
		Random generator = new Random();
		int roll;
		int myRank;
		if(getHand() != null)
		{
			myRank = evaluateHand();
		}
		else
		{
			myRank = 0;
		}
		//przed rozdaniem
		
		if(getHand() == null)
		{
			bluffed = false;
			//90% - check
			//10% - bet 3-6% zetonow (min 1)
			if(currBid == 0)
			{
				if(allIn)
				{
					return "check";
				}
				roll = generator.nextInt(100);
				if(roll >= 10)
				{
					return "check";
				}
				else
				{
					roll = generator.nextInt(3) + 3;
					bet = ((roll * getChips()) / 100);
					if(bet < 1)
					{
						return "check";
					}
					else
					{
						return "bet";
					}
				}
			}
			//call, o ile mozliwe
			else
			{
				if(allIn)
				{
					if(getBid() >= currBid)
					{
						return "check";
					}
					else if((currBid - getBid()) >= getChips())
					{
						return "all-in";
					}
					else
					{
						return "call";
					}
				}
				if(getBid() == currBid)
				{
					return "check";
				}
				else if((currBid - getBid()) <= getChips())
				{
					return "call";
				}
				else
				{
					return "all-in";
				}
			}
		}
		//high card
		//50% check
		//40% bet 3-6% zet
		//10% bluff: bet 3-6% zetonow
		else if(myRank == HIGH_CARD_RANK)
		{
			if(currBid == 0)
			{
				if(allIn)
				{
					return "check";
				}
				roll = generator.nextInt(100);
				if(roll >= 50)
				{
					return "check";
				}
				else if(roll >= 10)
				{					
					roll = generator.nextInt(3) + 3;
					bet = ((roll * getChips()) / 100);
					if(bet < 1)
					{
						return "check";
					}
					else
					{
						return "bet";
					}					
				}
				else
				{					
					bluffed = true;
					roll = generator.nextInt(3) + 3;
					bet = ((roll * getChips()) / 100);
					if(bet < 1)
					{
						return "check";
					}
					else
					{
						return "bet";
					}
				}
			}
			//jesli byl bluff: raise 3-6% zetonow (do 15% zet) lub call/fold 
			//jesli za duza stawka
			//jesli bez bluffu:
			//80% fold
			//20% call (do 10% zet)
			else
			{
				if(allIn)
				{
					if(getBid() >= currBid)
					{
						return "check";
					}
					else
					{
						roll = generator.nextInt(100);
						if((roll >= 20) || (currBid > ((10 * getChips()) / 100)))
						{
							return "fold";
						}
						else
						{
							return "call";
						}
					}
				}
				if(bluffed)
				{
					if(currBid <= ((15 * getChips()) / 100))
					{
						roll = generator.nextInt(3) + 3;
						raise = ((roll * getChips()) / 100);
						if(raise < 1)
						{
							return "call";
						}
						else
						{
							return "raise";
						}
					}
					else if(currBid <= ((20 * getChips()) / 100))
					{
						return "call";
					}
					else
					{
						return "fold";
					}
				}
				else
				{
					roll = generator.nextInt(100);
					if(roll >= 20)
					{
						return "fold";
					}
					else
					{
						if(currBid <= ((5 * getChips()) / 100))
						{
							return "call";
						}
						else
						{
							return "fold";
						}
					}
				}
			}
		}
		//pair
		//20% check
		//60% bet 3-6% zet
		//20% bluff: bet 3-6% zetonow
		else if(myRank == PAIR_RANK)
		{			
			if(currBid == 0)
			{
				if(allIn)
				{
					return "check";
				}
				roll = generator.nextInt(100);
				if(roll >= 40)
				{					
					roll = generator.nextInt(3) + 3;
					bet = ((roll * getChips()) / 100);
					if(bet < 1)
					{
						return "check";
					}
					else
					{
						return "bet";
					}					
				}
				else if(roll >= 20)
				{
					return "check";
				}				
				else
				{					
					bluffed = true;
					roll = generator.nextInt(3) + 3;
					bet = ((roll * getChips()) / 100);
					if(bet < 1)
					{
						return "check";
					}
					else
					{
						return "bet";
					}
				}
			}
			//jesli byl bluff: raise 3-6% zetonow lub call/fold 
			//jesli za duza stawka
			//jesli bez bluffu:
			//30% fold
			//55% call (do 10% zet)
			//15% raise (do 10% zet)
			else
			{
				if(allIn)
				{
					if(currBid <= ((10 * getChips()) / 100))
					{
						return "call";
					}
					else
					{
						roll = generator.nextInt(100);
						if(roll >= 20)
						{
							return "fold";
						}
						else
						{
							if((currBid - getBid()) >= getChips())
							{
								return "all-in";
							}
							else
							{
								return "call";
							}
						}
					}
				}
				if(bluffed)
				{
					if(currBid <= ((20 * getChips()) / 100))
					{
						roll = generator.nextInt(3) + 3;
						raise = ((roll * getChips()) / 100);
						if(raise < 1)
						{
							return "call";
						}
						else
						{
							return "raise";
						}
					}
					else if(currBid <= ((25 * getChips()) / 100))
					{
						return "call";
					}
					else
					{
						return "fold";
					}
				}
				else
				{
					roll = generator.nextInt(100);
					if(roll >= 45)
					{
						if(currBid <= ((10 * getChips()) / 100))
						{
							return "call";
						}
						else
						{
							return "fold";
						}
					}
					else if(roll <= 15)
					{
						return "fold";
					}
					else
					{
						if(currBid <= ((10 * getChips()) / 100))
						{
							roll = generator.nextInt(3) + 3;
							raise = ((roll * getChips()) / 100);
							if(raise < 1)
							{
								if((currBid - getBid()) < getChips())
								{
									return "call";
								}
								else if((currBid - getBid()) == getChips())
								{
									return "all-in";
								}
								else
								{
									return "fold";
								}
							}
							else
							{
								return "raise";
							}
						}
						else
						{
							return "fold";
						}
					}
				}
			}
		}
		//three/two pair
		//bet 3-6% zet
		else if((myRank == THREE_RANK) || (myRank == TWO_PAIR_RANK))
		{
			if(currBid == 0)
			{
				if(allIn)
				{
					return "check";
				}
				roll = generator.nextInt(3) + 3;
				bet = ((roll * getChips()) / 100);
				if(bet < 1)
				{
					return "check";
				}
				else
				{
					return "bet";
				}									
			}
			//10% call (do 15% zet)
			//90% raise 3-6% (do 10% zet)
			else
			{		
				if(allIn)
				{
					if(currBid <= ((20 * getChips()) / 100))
					{
						return "call";
					}
					else
					{
						roll = generator.nextInt(100);
						if(roll >= 70)
						{
							return "fold";
						}
						else
						{
							if((currBid - getBid()) >= getChips())
							{
								return "all-in";
							}
							else
							{
								return "call";
							}
						}
					}
				}
				roll = generator.nextInt(100);
				if(roll < 10)
				{
					if(currBid <= ((15 * getChips()) / 100))
					{
						return "call";
					}
					else
					{
						return "fold";
					}
				}
				else if(currBid <= ((10 * getChips()) / 100))
				{
					roll = generator.nextInt(3) + 3;
					raise = ((roll * getChips()) / 100);
					if(raise < 1)
					{
						if((currBid - getBid()) < getChips())
						{
							return "call";
						}
						else if((currBid - getBid()) == getChips())
						{
							return "all-in";
						}
						else
						{
							return "fold";
						}
					}
					else
					{
						return "raise";
					}
				}
				else
				{
					if(currBid <= ((10 * getChips()) / 100))
					{
						roll = generator.nextInt(3) + 3;
						raise = ((roll * getChips()) / 100);
						if(raise < 1)
						{
							if((currBid - getBid()) < getChips())
							{
								return "call";
							}
							else if((currBid - getBid()) == getChips())
							{
								return "all-in";
							}
							else
							{
								return "fold";
							}
						}
						else
						{
							return "raise";
						}
					}
					else
					{
						return "fold";
					}
				}
			}
		}
		//straight i kolor
		//bet 5-6% zet
		else if((myRank == STRAIGHT_RANK) || (myRank == FLUSH_RANK))
		{
			if(currBid == 0)
			{	
				if(allIn)
				{
					return "check";
				}
				roll = generator.nextInt(1) + 5;
				bet = ((roll * getChips()) / 100);
				if(bet < 1)
				{
					return "check";
				}
				else
				{
					return "bet";
				}									
			}
			//raise 5-6% (do 30% zet)
			else
			{	
				if(allIn)
				{
					if(currBid <= getBid())
					{
						return "check";
					}
					else if((currBid - getBid()) >= getChips())
					{
						return "all-in";
					}
					else
					{
						return "call";
					}
				}
				if(currBid <= ((30 * getChips()) / 100))
				{
					roll = generator.nextInt(1) + 5;
					raise = ((roll * getChips()) / 100);
					if(raise < 1)
					{
						if((currBid - getBid()) < getChips())
						{
							return "call";
						}
						else if((currBid - getBid()) == getChips())
						{
							return "all-in";
						}
						else
						{
							return "fold";
						}
					}
					else
					{
						return "raise";
					}
				}
				else
				{
					if((currBid - getBid()) < getChips())
					{
						return "call";
					}
					else
					{
						return "all-in";
					}					
				}
			}
		}
		//full i wyzej
		//bet 5-6% zet
		else
		{
			if(currBid == 0)
			{	
				if(allIn)
				{
					return "check";
				}
				roll = generator.nextInt(1) + 5;
				bet = ((roll * getChips()) / 100);
				if(bet < 1)
				{
					return "check";
				}
				else
				{
					return "bet";
				}									
			}
			//raise 5-6% (do 50% zet)
			else
			{	
				if(allIn)
				{
					return "all-in";
				}
				if(currBid <= ((50 * getChips()) / 100))
				{
					roll = generator.nextInt(1) + 5;
					raise = ((roll * getChips()) / 100);
					if(raise < 1)
					{
						if((currBid - getBid()) < getChips())
						{
							return "call";
						}
						else if((currBid - getBid()) == getChips())
						{
							return "all-in";
						}
						else
						{
							return "fold";
						}
					}
					else
					{
						return "raise";
					}
				}
				else
				{
					if((currBid - getBid()) < getChips())
					{
						return "call";
					}
					else
					{
						return "all-in";
					}					
				}
			}
		}
	}
	public int bet()
	{
		return bet;
	}
	public int raise()
	{
		return raise;
	}
}
